#pragma once

#include <memory>
#include "Comm.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"
#include "Connection.hpp"
#include "HandlerConnection.hpp"

using namespace socket_ns;

class Listener
{
public:
    Listener(uint16_t port, HandlerConnection hc, int pipefdwrite, int pipefdread)
        : _port(port),
          _listensock(std::make_unique<TcpSocket>()),
          _hc(hc),
          _pipefdwrite(pipefdwrite),
          _pipefdread(pipefdread)
    {
        InetAddr addr("0", _port);
        _listensock->BuildListenSocket(addr);
        SetNonBlock(_listensock->SockFd());
    }
    void Accpet(Connection *conn)
    {
        while (true)
        {
            InetAddr clientaddr;
            int code = 0;
            //如果不设置非阻塞，则其中一个进程会收到accpet，另外几个就会阻塞在这里
            //此时如果有一个client连接来了，连接到了不同进程，则他又会将原先已经建立连接的进程给阻塞住，这就麻烦了
            int sockfd = _listensock->Accepter(&clientaddr, &code);
            if (sockfd > 0)
            {
                // TODO
                conn->Self()->AddConnection(
                    sockfd,
                    EPOLLIN | EPOLLET,
                    std::bind(&HandlerConnection::HandlerRecv, &_hc, std::placeholders::_1),
                    std::bind(&HandlerConnection::HandlerSend, &_hc, std::placeholders::_1),
                    std::bind(&HandlerConnection::HandlerExcept, &_hc, std::placeholders::_1));
            }
            else
            {
                if (code == EWOULDBLOCK || code == EAGAIN)
                {
                    LOG(DEBUG, "accepter all link!\n");
                    break;
                }
                else if (code == EINTR)
                {
                    LOG(DEBUG, "accepter interupt by signal!\n");
                    continue;
                }
                else
                {
                    LOG(WARNNING, "accept error! -- %s\n",strerror(errno));
                    break;
                }
            }
            return;
        }
    }
    void WakeProccess(Connection *conn)
    {
        std::string buffer = std::to_string(1);
        ssize_t n = ::write(_pipefdwrite, buffer.c_str(), buffer.size());
        if (n < 0)
        {
            LOG(FATAL, "wakeup child proccess fail-write into pipe fail");
            return;
        }
        else
        {
            // LOG(DEBUG, "wakeup child proccess success");
        }
        // sleep(1);
        // }
    }
    int SockFd()
    {
        return _listensock->SockFd();
    }
    ~Listener()
    {
        _listensock->Close();
    }

private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensock;
    HandlerConnection _hc;
    int _pipefdwrite;
    int _pipefdread;
};